<?php

/**
 * Created by IntelliJ IDEA.
 * User: ty42
 * Date: 5/13/16
 * Time: 2:32 PM
 */
class Wfsearchm extends CI_Model
{
    public static $sc = null;  // sphinx client instance
    public static $wfdb = null;

    const DOC_TYP_HY = "10";
    const DOC_TYP_XW = "11";
    const DOC_TYP_QK = "12";

    static $tbl_arr = array(
        self::DOC_TYP_HY => "dbo_hy",
        self::DOC_TYP_XW => "dbo_xw",
        self::DOC_TYP_QK => "dbo_qk",
    );

    static $dir_prefix_arr = array(
        self::DOC_TYP_HY => "huiyi",
        self::DOC_TYP_XW => "xuewei",
        self::DOC_TYP_QK => "qikan",
    );


    function __construct()
    {
        parent::__construct();
    }

    /**
     * @return SphinxClient
     */
    private function getInstanceOfSphinxClient()
    {
        if (!self::$sc) {
            $this->load->library('sphinxclient');

            $cl = new SphinxClient();

            $cl->SetServer(CORESEEK_IP_WFDOCUMENT, CORESEEK_PORT_WFDOCUMENT);
            $cl->SetConnectTimeout(1);
            $cl->SetArrayResult(true);
            $cl->SetWeights(array(100, 1));

            self::$sc = $cl;
        }

        return self::$sc;
    }

    /**
     * @return CI_DB_query_builder
     */
    private function getInstanceOfWFDB()
    {
        if (!self::$wfdb) {
            self::$wfdb = $this->load->database('wfdb', true);
        }

        return self::$wfdb;
    }

    public function getSelectStrByDocType($doc_type)
    {
        $cond_conf = array(
            self::DOC_TYP_HY => array(
                "id" => "id",
                "article_id" => "ArticleID",
                "title" => "论文题名",
                "keywords" => "关键词",
                "author" => "zz_info",
                "publication_time" => "出版时间",
                "journal" => "母体文献",
                "abstract" => "文摘",
                "path" => "全文路径",
            ),
            self::DOC_TYP_XW => array(
                "id" => "id",
                "article_id" => "ArticleID",
                "title" => "论文题名",
                "keywords" => "关键词",
                "author" => "作者",
                "publication_time" => "学位年度",
                "journal" => "",
                "abstract" => "文摘",
                "path" => "全文路径",
            ),
            self::DOC_TYP_QK => array(
                "id" => "id",
                "article_id" => "ArticleID",
                "title" => "F_Title",
                "keywords" => "f_keyword",
                "author" => "zz_xm",
                "publication_time" => "f_year",
                "journal" => "",
                "abstract" => "F_Abstract",
                "path" => "全文路径",
            ),
        );
        $cond = $cond_conf[$doc_type];

        $templates = array();
        foreach ($cond as $v => $k) {
            $k = $k ? "`$k`" : "''";
            $templates[] = "$k as `$v`";
        }
        
        return implode(", ", $templates);
    }
    
    
    protected function filterAuthor($title)
    {
        if (empty($title)) {
            return "";
        }
        if (strpos($title, "^") !== false) {
            $title = preg_replace("/\^[A-Z0-9]*/", " ", $title);
        }
        $title = str_replace("%", " ", $title);
        $title = str_replace(";", " ", $title);

        $tmp = explode(" ", $title);
        $result = array();
        foreach ($tmp as $item) {
            if ($item) {
                $result[] = $item;
            }
        }
        return implode(" ", $result);
    }
    
    
    protected function filterKeywords($keywords)
    {
        if (empty($keywords)) {
            return "";
        }
        $keywords = str_replace("%", " ", $keywords);
        $keywords = str_replace(";", " ", $keywords);

        $tmp = explode(" ", $keywords);
        $result = array();
        foreach ($tmp as $item) {
            if ($item) {
                $result[] = $item;
            }
        }
        return implode(" ", $result);
    }

    protected function filterPubTime($pub_time, $dt_fmt)
    {
        if (strlen($pub_time) > 4) {
            $pub_time = date($dt_fmt, strtotime($pub_time));
        } else if (strlen($pub_time) == 4){
            $pub_time = $pub_time.'年';
        }
        return $pub_time;
    }
    
    protected function genDocByRecord($value, $doc_type, $dt_fmt = '', $max_len_abs = 0)
    {
        $value["author"] = $this->filterAuthor($value["author"]);
        $value["keywords"] = $this->filterKeywords($value["keywords"]);

        if ($dt_fmt) {
            $value["publication_time"] = $this->filterPubTime($value["publication_time"], $dt_fmt);
        }

        if ($max_len_abs) {
            if ( ! function_exists('ellipsize')){
                $this->load->helper('text');
            }
            $value['abstract'] = ellipsize($value["abstract"], $max_len_abs);
        }

        $did = $doc_type . $value["id"];
        $value["did"] = $did;
//        $value["url_detail"] = site_url("literature_search/detail/{$did}") . '?attr=detail';

        return $value;
    }
    

    protected function GetDocListByDocType($id_arr, $doc_type)
    {
        $result = array();
        if (isset(self::$tbl_arr[$doc_type])) {
            $select_str = $this->getSelectStrByDocType($doc_type);
            $db = $this->getInstanceOfWFDB();
            $db->select($select_str);
            $db->where_in("id", $id_arr);
            $query = $db->get(self::$tbl_arr[$doc_type]);
            if ($query) {
                $res = $query->result_array();

                foreach ($res as $value) {
                    $doc = $this->genDocByRecord($value, $doc_type, 'Y年m月d日', 300);
                    $result[$doc["did"]] = $doc;
                }
            }
        }
        return $result;
    }

    public function getDocTypeByDid($did)
    {
        return substr($did, 0, 2);
    }

    public function getDocIDByDid($did)
    {
        return substr($did, 2);
    }
    
    public function getDirPrefixByDocType($doc_type)
    {
        return isset(self::$dir_prefix_arr[$doc_type]) ? self::$dir_prefix_arr[$doc_type] : "";
    }


    /**
     * 根据自定义 did 获取文档列表
     * @param $did_arr
     * @return array
     */
    protected function getDocList($did_arr)
    {
        if (empty($did_arr)) {
            return array();
        }

        # 三种类型文档存在3张表里, 需要分别获取
        $map_arr = array();
        foreach ($did_arr as $did) {
            $doc_type = $this->getDocTypeByDid($did);
            if (!isset(self::$tbl_arr[$doc_type])) {
                continue;
            }

            # $may_arr 存储映射关系: "文档类型" => "实际文档id数组"
            if (!isset($map_arr[$doc_type])) {
                $map_arr[$doc_type] = array($this->getDocIDByDid($did));
            }
            else {
                $map_arr[$doc_type][] = $this->getDocIDByDid($did);
            }
        }

        $result = array();
        foreach ($map_arr as $doc_type => $id_arr) {
            # 每种文档按 id 数组获取一次
            $docs = $this->GetDocListByDocType($id_arr, $doc_type);
            foreach ($docs as $k => $v) {
                $result[$k] = $v;
            }
        }

        # 按初始顺序拼装数据
        $ordered_result = array();
        foreach ($did_arr as $did) {
            if (!isset($result[$did])) {
                continue;
            }
            $ordered_result[] = $result[$did];
        }
        return $ordered_result;
    }

    public function queryByCommon($keyword, $mode = '', $page = 1, $per_page = 10)
    {
        if (is_array($keyword)) {
            $keyword = implode(" ", $keyword);
        }
        if (empty($keyword)) {
            return array();
        }
        if (!$page) {
            $page = 1;
        }
        $cl = $this->getInstanceOfSphinxClient();

        $cl->SetLimits(intval(($page - 1) * $per_page), intval($per_page));

        $cl->SetRankingMode(SPH_RANK_PROXIMITY_BM25);


        if ($mode == 'title') {
            $cl->SetMatchMode(SPH_MATCH_EXTENDED);
            $cl->SetSortMode(SPH_SORT_EXTENDED, 'publication_time DESC, @weight DESC, title ASC');
            $res = $cl->Query("@title $keyword", '*');
        }
        elseif ($mode == 'author') {
            $cl->SetMatchMode(SPH_MATCH_EXTENDED);
            $cl->SetSortMode(SPH_SORT_EXTENDED, 'publication_time DESC');
            $res = $cl->Query("@author $keyword", '*');
        }
        elseif ($mode == 'newest') {
            $cl->SetMatchMode(SPH_MATCH_ALL);
            $cl->SetSortMode(SPH_SORT_EXTENDED, 'publication_time DESC, @weight DESC');
            $res = $cl->Query($keyword, '*');
        }
        elseif ($mode == 'source') {
            $cl->SetMatchMode(SPH_MATCH_EXTENDED);
            $cl->SetSortMode(SPH_SORT_EXTENDED, 'publication_time DESC');
            $res = $cl->Query("@journal $keyword", '*');
        }
        else {
            # 按相关度搜索
            $cl->SetMatchMode(SPH_MATCH_ALL);
            $cl->SetSortMode(SPH_SORT_EXTENDED, 'publication_time DESC');
            $res = $cl->Query($keyword, '*');
        }

        $total_found = isset($res["total_found"]) ? $res["total_found"] : 0;

        $data = $res["matches"];
        if (!empty($data)) {
            $data = $this->getDocList(array_column($data, "id"));
        }
        else {
            $data = array();
        }

        return array("list" => $data, "count"=> $total_found);
    }

    public function queryByDid($did)
    {
        $doc_type = $this->getDocTypeByDid($did);
        if (!isset(self::$tbl_arr[$doc_type])) {
            return array();
        }
        
        $doc_id = $this->getDocIDByDid($did);

        $db = $this->getInstanceOfWFDB();
        $select_str = $this->getSelectStrByDocType($doc_type);
        $db->select($select_str);
        $db->where("id", $doc_id);
        $query = $db->get(self::$tbl_arr[$doc_type]);
        if ($query) {
            $res = $query->row_array();
            $doc = $this->genDocByRecord($res, $doc_type, 'Y年m月d日');
        }
        else {
            $doc = array();
        }

        return $doc;
    }
}